package browser

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/chromedp/chromedp"
)

// GetQueryOption 根据选择器类型返回对应的查询选项
func GetQueryOption(selectorType string) chromedp.QueryOption {
	switch selectorType {
	case "id":
		return chromedp.ByID
	case "query":
		return chromedp.ByQuery
	default:
		return chromedp.ByQuery
	}
}

// Screenshot 打开浏览器，访问指定URL并截图保存
func Screenshot(ctx context.Context, url string, savePath string) (string, error) {
	ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	var buf []byte

	// 执行浏览器操作
	err := chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.WaitVisible("body", chromedp.ByQuery),
		chromedp.Sleep(2*time.Second), // 等待页面加载
		chromedp.CaptureScreenshot(&buf),
	)

	if err != nil {
		return "", fmt.Errorf("浏览器操作失败: %v", err)
	}

	// 如果未指定保存路径，使用默认路径
	if savePath == "" {
		savePath = "screenshot.png"
	}

	// 确保目录存在
	dir := filepath.Dir(savePath)
	if dir != "." && dir != "" {
		if err := os.MkdirAll(dir, 0755); err != nil {
			return "", fmt.Errorf("创建目录失败: %v", err)
		}
	}

	// 保存截图
	if err := os.WriteFile(savePath, buf, 0644); err != nil {
		return "", fmt.Errorf("保存截图失败: %v", err)
	}

	// 获取绝对路径
	absPath, err := filepath.Abs(savePath)
	if err != nil {
		absPath = savePath
	}

	return absPath, nil
}

// ClickElement 点击指定元素
func ClickElement(ctx context.Context, url string, selector string, selectorType string) (string, error) {
	ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	byQuery := GetQueryOption(selectorType)

	err := chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.WaitVisible("body", chromedp.ByQuery),
		chromedp.Sleep(1*time.Second),
		chromedp.WaitVisible(selector, byQuery),
		chromedp.Click(selector, byQuery),
		chromedp.Sleep(1*time.Second),
	)

	if err != nil {
		return "", fmt.Errorf("点击操作失败: %v", err)
	}

	return "点击成功！", nil
}

// InputText 在指定输入框中输入文本
func InputText(ctx context.Context, url string, selector string, text string, selectorType string) (string, error) {
	ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	byQuery := GetQueryOption(selectorType)

	err := chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.WaitVisible("body", chromedp.ByQuery),
		chromedp.Sleep(1*time.Second),
		chromedp.WaitVisible(selector, byQuery),
		chromedp.Click(selector, byQuery),
		chromedp.Clear(selector, byQuery),
		chromedp.SendKeys(selector, text, byQuery),
		chromedp.Sleep(1*time.Second),
	)

	if err != nil {
		return "", fmt.Errorf("输入操作失败: %v", err)
	}

	return fmt.Sprintf("已输入文本: %s", text), nil
}

// ExecuteJavaScript 执行 JavaScript 代码并返回结果
func ExecuteJavaScript(ctx context.Context, url string, jsCode string) (string, error) {
	ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	var result interface{}

	err := chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.WaitVisible("body", chromedp.ByQuery),
		chromedp.Sleep(1*time.Second),
		chromedp.Evaluate(jsCode, &result),
	)

	if err != nil {
		return "", fmt.Errorf("执行 JavaScript 失败: %v", err)
	}

	return fmt.Sprintf("执行结果: %v", result), nil
}

// GetPageTitle 获取页面标题
func GetPageTitle(ctx context.Context, url string) (string, error) {
	ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	var title string

	err := chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.WaitVisible("body", chromedp.ByQuery),
		chromedp.Sleep(1*time.Second),
		chromedp.Title(&title),
	)

	if err != nil {
		return "", fmt.Errorf("获取标题失败: %v", err)
	}

	return title, nil
}

// GetElementText 获取指定元素的文本内容
func GetElementText(ctx context.Context, url string, selector string, selectorType string) (string, error) {
	ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	var text string
	byQuery := GetQueryOption(selectorType)

	err := chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.WaitVisible("body", chromedp.ByQuery),
		chromedp.Sleep(1*time.Second),
		chromedp.WaitVisible(selector, byQuery),
		chromedp.Text(selector, &text, byQuery),
	)

	if err != nil {
		return "", fmt.Errorf("获取文本失败: %v", err)
	}

	return text, nil
}

// WaitForElement 等待指定元素出现
func WaitForElement(ctx context.Context, url string, selector string, selectorType string, timeoutSeconds int) (string, error) {
	if timeoutSeconds <= 0 {
		timeoutSeconds = 10
	}

	ctx, cancel := context.WithTimeout(ctx, time.Duration(timeoutSeconds)*time.Second)
	defer cancel()

	byQuery := GetQueryOption(selectorType)

	err := chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.WaitVisible("body", chromedp.ByQuery),
		chromedp.WaitVisible(selector, byQuery),
	)

	if err != nil {
		return "", fmt.Errorf("等待元素超时或失败: %v", err)
	}

	return fmt.Sprintf("元素已出现: %s", selector), nil
}

